package com.binary.coder.gift.core.common.utils;


import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

/**
 * 1 getData 日期或字符串转int数组中，便于再使用
 * 2 toDateNum  转换为日期数字
 * 3 日期转换字符串
 * 4 字符串转日期
 */
public class DateUtils extends DateUtil {

    /**
     * 清除 时分秒,毫秒
     *
     * @param calendar
     * @return
     */
    public static Calendar clearTime(Calendar calendar) {
        if (calendar == null) {
            return null;
        }
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    public static Date clearTime(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 公共，根据格式转字符串
     *
     * @param date
     * @param format
     * @return
     */
    @Deprecated
    public static String getFormatTimeString(Date date, String format) {
        SimpleDateFormat toTimeFormat = new SimpleDateFormat(format);
        return toTimeFormat.format(date);
    }

    /**
     * 转换年月日格式
     *
     * @param timeMillis
     * @return
     */
    @Deprecated
    public static String covertToDateString(long timeMillis) {
        return getDateString(timeMillis);
    }

    public static String getDateString(long timeMillis) {
        if (timeMillis > 0) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(timeMillis);
            int[] data = getData(calendar);
            return String.format("%04d-%02d-%02d", data[0], data[1], data[2]);
        } else {
            return "";
        }
    }

    public static String getDateString(Date date) {
        int[] data = getData(date);
        return String.format("%04d-%02d-%02d", data[0], data[1], data[2]);
    }

    public static String getTimeString(long timeMillis) {
        if (timeMillis > 0) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(timeMillis);
            int[] data = getData(calendar);
            return String.format("%04d-%02d-%02d %02d:%02d:%02d", data[0], data[1], data[2], data[3], data[4], data[5]);
        } else {
            return "";
        }
    }

    public static String getTimeString(Date date) {
        int[] data = getData(date);
        return String.format("%04d-%02d-%02d %02d:%02d:%02d", data[0], data[1], data[2], data[3], data[4], data[5]);
    }

    public static String getXTimeString(Date date) {
        int[] data = getData(date);
        return String.format("%04d-%02d-%02d %02d:%02d:%02d.%03d", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
    }

    public static String getXXTimeString(Date date) {
        int[] data = getData(date);
        return toDateNum(data, 7) + "";
    }

    public static String getDateString() {
        return getDateString(Calendar.getInstance().getTime());
    }

    public static String getTimeString() {
        return getTimeString(Calendar.getInstance().getTime());
    }

    public static String getXTimeString() {
        return getXTimeString(Calendar.getInstance().getTime());
    }

    public static String getXXTimeString() {
        return getXXTimeString(Calendar.getInstance().getTime());
    }


    /**
     * 字符串必须是年,月，日，时，分，秒，毫秒的顺序
     *
     * @param str
     * @return
     */
    public static Date toDate(String str) {
        //遍历字符串
        int[] values = getData(str);

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, values[0] > 100 ? values[0] : (values[0] + 2000));//如果时2位，默认处理为2000年以后
        calendar.set(Calendar.MONTH, values[1] > 0 ? (values[1] - 1) : 0);//【注意】：月份从0开始的，所以默认为0(1月)
        calendar.set(Calendar.DATE, values[2] > 0 ? values[2] : 1);//日期从1开始的，所以默认为1号

        calendar.set(Calendar.HOUR_OF_DAY, values[3]);
        calendar.set(Calendar.MINUTE, values[4]);
        calendar.set(Calendar.SECOND, values[5]);
        calendar.set(Calendar.MILLISECOND, values[6]);

        return calendar.getTime();
    }


    /**
     * 提取日期中的数值
     *
     * @param date
     * @return
     */
    public static int[] getData(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getData(calendar);
    }

    /**
     * 提取日期中的数值
     *
     * @param calendar
     * @return
     */
    public static int[] getData(Calendar calendar) {
        int[] data = new int[7];
        data[0] = calendar.get(Calendar.YEAR);
        data[1] = calendar.get(Calendar.MONTH) + 1;//【注意】： 月份从0开始的，需要加1.
        data[2] = calendar.get(Calendar.DAY_OF_MONTH);
        data[3] = calendar.get(Calendar.HOUR_OF_DAY);
        data[4] = calendar.get(Calendar.MINUTE);
        data[5] = calendar.get(Calendar.SECOND);
        data[6] = calendar.get(Calendar.MILLISECOND);
        return data;
    }

    /**
     * 提取日期字符串中的数值
     *
     * @param str
     * @return
     */
    public static int[] getData(String str) {
        String temp = str;
        //遍历字符串
        int[] values = new int[]{0, 0, 0, 0, 0, 0, 0};//年,月，日，时，分，秒，毫秒
        int vIndex = 0;
        int l = temp.length();

        for (int i = 0; i < l; ) {
            char c = temp.charAt(i);
            //有效数字开头
            if ('0' <= c && c <= '9') {
                for (int j = i; j < l; j++) {
                    c = temp.charAt(j);
                    if (c > '9' || c < '0') {
                        //有效数字结束
                        String v = temp.substring(i, j);
                        values[vIndex++] = Integer.parseInt(v);
                        i = j;
                        break;
                    } else if (j >= l - 1) {
                        //字符串串完成
                        String v = temp.substring(i, j + 1);
                        values[vIndex++] = Integer.parseInt(v);
                        i = j + 1;
                        break;
                    }
                }
            } else {
                i++;
            }
        }
        return values;
    }

    /**
     * 日期转数值
     *
     * @param str
     * @return
     */
    public static long toDateNum(String str) {
        return toDateNum(str, 7);
    }

    /**
     * 日期转数值
     *
     * @param date
     * @return
     */
    public static long toDateNum(Calendar date) {
        return toDateNum(getData(date), 7);
    }

    /**
     * 日期转数值
     *
     * @param str
     * @param sl  截至到年月日时分秒毫秒的位置
     * @return
     */
    public static long toDateNum(String str, int sl) {
        int[] values = getData(str);
        if (values == null || values.length == 0) {
            return 0;
        }
        return toDateNum(values, sl);
    }

    /**
     * 日期格式数组，转出数字
     * 如：20200102125632703
     *
     * @param values
     * @param sl
     * @return
     */
    public static long toDateNum(int[] values, int sl) {
        if (values == null || values.length == 0) {
            return 0;
        }
        // 第一位
        long t = values[0];
        // 中间位置
        for (int i = 1; i < sl - 1 && i < values.length; i++) {
            t = t * 100 + values[i];
        }
        // 最后一位
        if (sl - 1 < values.length) {
            if (sl - 1 == 6) {
                t = t * 1000 + values[sl - 1];
            } else {
                t = t * 100 + values[sl - 1];
            }
        }
        return t;
    }

    public static long toDateNum(Calendar calendar, int sl) {
        int[] values = getData(calendar);
        if (values == null || values.length == 0) {
            return 0;
        }
        return toDateNum(values, sl);
    }

    /**
     * 判断闰年
     *
     * @param year
     * @return
     */
    public static boolean leapYear(int year) {
        return ((year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? true : false);
    }

    /**
     * 获取一年天数
     *
     * @param year
     * @return
     */
    public static int getYearDayNumber(int year) {
        return leapYear(year) ? 366 : 365;
    }

    /**
     * 获取该月天数量
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * @param dateStr 2020-02-01
     * @return
     */
    public static int getDaysOfMonth(String dateStr) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM
            Date date = simpleDateFormat.parse(dateStr);
            return getDaysOfMonth(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static String[] getDaysOfMonthArray(String dateStr) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM
            Date date = simpleDateFormat.parse(dateStr);
            int dayNum = getDaysOfMonth(date);
            String[] days = new String[dayNum];
            for (int i = 1; i <= dayNum; i++) {
                days[i - 1] = String.valueOf(i < 10 ? "0" + i : i);
            }
            return days;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 字符串转Date
     *
     * @param dateStr
     * @param format  "yyyy-MM-dd"
     * @return
     */
    public static Date strToDate(String dateStr, String format) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);//注意月份是MM
            Date date = simpleDateFormat.parse(dateStr);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static int getDateYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    public static int getDateYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    public static int getDateMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    public static int getDateMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    public static int getDateDay() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DATE);
    }

    public static int getDateDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE);
    }

    /**
     * 获取当前时间剩余月份
     *
     * @return
     */
    public static String[] getSurplusMonth() {
        int currentMonth = getDateMonth();//当前月份
        int totalMonth = 12;//一年12个月
        int monthSize = totalMonth - currentMonth;
        String[] month = new String[monthSize];//剩余月份数组
        int index = currentMonth;
        int count = 0;
        while (count < monthSize) {
            index++;
            count++;
            month[count - 1] = String.valueOf(index < 10 ? "0" + (index) : (index));
            System.out.println(month[count - 1]);
        }
        return month;
    }

    /**
     * month的字符串比较 month的pattern yyyy-MM
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int monthDateStrCompare(String date1, String date2) {
        String[] ss1 = date1.split("-");
        String[] ss2 = date2.split("-");
        if (ss1.length != ss2.length) {
            throw new IllegalStateException("比较的对象格式不一致");
        }
        for (int index = 0; index < ss1.length; index++) {
            int i1 = Integer.parseInt(ss1[index]);
            int i2 = Integer.parseInt(ss2[index]);
            if (i1 == i2) {
                continue;
            } else {
                return i1 > i2 ? 1 : -1;
            }
        }
        return 0;
    }

    public static String getFirstTimeOfDay(LocalDateTime localDateTime) {
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime firstTimeOfDay = localDateTime.withHour(0).withMinute(0).withSecond(0);
        return firstTimeOfDay.format(pattern);
    }

    public static String getLastTimeOfDay(LocalDateTime localDateTime) {
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime lastTimeOfDay = localDateTime.withHour(23).withMinute(59).withSecond(59);
        return lastTimeOfDay.format(pattern);
    }

    /**
     * LocalDate转Date
     *
     * @param localDate localDate
     * @return Date
     * @author zgs
     * @date 2021/12/29 13:52
     */
    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDateTime转Date
     *
     * @param localDateTime localDateTime
     * @return Date
     * @author zgs
     * @date 2021/12/29 13:52
     */
    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * Date转LocalDate
     *
     * @param date date
     * @return Date
     * @author zgs
     * @date 2021/12/29 13:52
     */
    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * Date转LocalDateTime
     *
     * @param date date
     * @return Date
     * @author zgs
     * @date 2021/12/29 13:52
     */
    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 获取两个日期之前的所有月份
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getBetweenMonth(LocalDate startDate, LocalDate endDate) {
        List<String> list = Lists.newArrayList();
        long distance = ChronoUnit.MONTHS.between(startDate, endDate);
        Stream.iterate(startDate, d -> d.plusMonths(1)).limit(distance + 1).forEach(f -> {
            list.add(f.format(DateTimeFormatter.ofPattern("yyyy-MM")));
        });
        return list;
    }

    /**
     * 获取一段时间的每一天日期
     *
     * @param start
     * @param end
     * @return
     * @throws Exception
     */

    public static List<String> getBetweenDate(String start, String end) {
        List<String> list = Lists.newArrayList();
        LocalDate startDate = LocalDate.parse(start);
        LocalDate endDate = LocalDate.parse(end);
        long distance = ChronoUnit.DAYS.between(startDate, endDate);
        if (distance < 1) {
            return list;
        }
        Stream.iterate(startDate, d -> d.plusDays(1)).limit(distance + 1).forEach(f -> list.add(f.toString()));
        return list;
    }

    /**
     * 获取月份的每周起始时间
     *
     * @param month
     */
//    public static Map<Integer, Map<String, LocalDate>> getWeekDays(String month) {
//        String offsetDays = SysConfigCenter.getValByKey("month_year_day");
//        int offset = StringUtils.isNotBlank(offsetDays) ? Integer.parseInt(offsetDays) : 2;
//        LocalDate firstDay = TimeUtils.getStartDayOfMonthMinus(TimeUtils.toLocalDate(month + "-01"), offset);
//        LocalDate lastDay = TimeUtils.toLocalDate(month + "-01").with(TemporalAdjusters.lastDayOfMonth()).minusDays(offset);
//
//        // 每周的开始日期和结束日期
//        Map<Integer, Map<String, LocalDate>> weekDays = new LinkedHashMap<>();
//        int i = 1;
//        while (firstDay.compareTo(lastDay) <= 0) {
//            Map<String, LocalDate> dateMap = new LinkedHashMap<>();
//            dateMap.put("startDate", firstDay);
//
//            firstDay = firstDay.plusWeeks(1);
//            // 完整一周的最后一天还需要减去一天
//            LocalDate endDate = firstDay.minusDays(1);
//            // 加上一周后大于当月的最后一天日期，则为最后一周，那最后一周的天数为7天减去超出最后一天的天数
//            if (firstDay.compareTo(lastDay) > 0) {
//                endDate = lastDay;
//            }
//            dateMap.put("endDate", endDate);
//            weekDays.put(i, dateMap);
//            i++;
//        }
//        return weekDays;
//    }

    /**
     * 获取当前日期是第几周
     *
     * @param today
     * @return
     */
//    public static Integer getWeekNo(LocalDate today) {
//        String month = today.format(DateTimeFormatter.ofPattern("yyyy-MM"));
//        Map<Integer, Map<String, LocalDate>> weekDays = getWeekDays(month);
//        for (Map.Entry<Integer, Map<String, LocalDate>> entry : weekDays.entrySet()) {
//            Integer weekNo = entry.getKey();
//            Map<String, LocalDate> rangDays = entry.getValue();
//            LocalDate startDate = rangDays.get("startDate");
//            LocalDate endDate = rangDays.get("endDate");
//            if (!today.isBefore(startDate) && !today.isAfter(endDate)) {
//                return weekNo;
//            }
//        }
//        return 1;
//    }
    public static void main(String[] args) {
        List<String> betweenMonth = getBetweenMonth(LocalDate.of(2023, 1, 1), LocalDate.now());
        betweenMonth.forEach(item -> {
            System.out.println(item);
        });
    }
}
